package com.demo.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.context.annotation.*;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.ClassUtils;
import org.springframework.web.WebApplicationInitializer;

/**
 * {@link Conditional}注解为Bean的实例化设置条件。只有里面的{@link Condition}的实现类的matches方法返回true时才实例化为Bean
 */
@Configuration
@ConditionalOnAClass(className = "org.apache.catalina.startup.Tomcat")
public class TomcatConfiguration {

//    @Value("${port:8080}")    // 错误，无法解析占位符，类型转换错误 -> @Value("8848")正确
//    private int port;

    private final ServerProperties serverProperties;

    public TomcatConfiguration(ServerProperties serverProperties) {
        this.serverProperties = serverProperties;
    }

    /**
     * spring boot应用程序启动流程：
     *
     * @see SpringApplication#createApplicationContext()    创建IOC容器
     * @see AnnotationConfigServletWebServerApplicationContext
     * @see AbstractApplicationContext#refresh()    抽象类刷新上下文
     * @see ServletWebServerApplicationContext#onRefresh()  刷新springboot上下文
     * @see ServletWebServerApplicationContext#createWebServer()    创建web服务器
     * @see TomcatServletWebServerFactory#getWebServer(org.springframework.boot.web.servlet.ServletContextInitializer...) 实例化tomcat容器
     * @see ServletWebServerApplicationContext#selfInitialize(javax.servlet.ServletContext) 初始化servlet容器
     * @see ServletContextInitializer 初始化tomcat容器时，会从spring容器注入所有实现了{@link ServletContextInitializer}接口的Bean,并调用它们的onStartup()方法，类似于{@link WebApplicationInitializer}的作用。但它只用于spring boot的应用程序。
     */
    @SuppressWarnings("JavadocReference")
    @Bean
    TomcatServletWebServerFactory servletWebServerFactory() {
        //使用带参的构造方法实例化TomcatServletWebServerFactory
//        return new TomcatServletWebServerFactory(8081);
//        return new TomcatServletWebServerFactory("/springboot",8081);
        return new TomcatServletWebServerFactory(this.serverProperties.getPort());
    }
}
